/* 
 * Created on 2007-4-23
 * Last modified on 2007-4-23
 * Powered by YeQiangWei.com
 */
package com.yeqiangwei.commons.image;

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;

import org.apache.log4j.Logger;

import com.yeqiangwei.commons.image.gif.AnimatedGifEncoder;
import com.yeqiangwei.commons.image.gif.GifDecoder;
import com.yeqiangwei.commons.util.ArithHelper;
import com.yeqiangwei.commons.util.TypeChange;
import com.yeqiangwei.commons.util.ValidatorHelper;

/**
 * 
 * @author yeqiangwei
 */
public class ImageGif extends ImageOperate {

	private static final Logger logger = Logger.getLogger(ImageGif.class);

	@Override
	public boolean incise(File file, String filePathAndName, int w, int h, int x, int y, int x_w, int y_h) {
		boolean bea = false;
		try {
			FileInputStream fis = new FileInputStream(file);
			BufferedInputStream bis = new BufferedInputStream(fis);
			this.clip(bis, filePathAndName, w, h, x, y, x_w, y_h);
			bis.close();
			fis.close();
		} catch (IOException e) {
			logger.error(e.toString());
		}
		return bea;
	}

	/**
	 * 
	 * @param bi
	 * @param delays
	 * @param filePathAndName
	 * @param wimgs
	 *            合成图片
	 * @param w
	 * @param h
	 * @param x
	 * @param y
	 * @param x_w
	 * @param y_h
	 * @throws IOException
	 */
	private void gif(List<BufferedImage> bi, List<Integer> delays, Image[] wimgs, String filePathAndName, int w, int h, int x, int y, int x_w, int y_h) throws IOException {
		if (!ValidatorHelper.isEmpty(bi) && !ValidatorHelper.isEmpty(delays) && bi.size() == delays.size()) {
			FileOutputStream out = new FileOutputStream(filePathAndName);
			AnimatedGifEncoder gifEncoder = new AnimatedGifEncoder();
			gifEncoder.start(out);
			for (int i = 0; i < bi.size(); i++) {
				java.awt.image.BufferedImage tag = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
				BufferedImage img = bi.get(i);
				Graphics2D g2d = tag.createGraphics();
				// g2d.setBackground(Color.BLUE);
				// g2d.drawString("yeqiangwei.com", 50, 100);
				if (x != -1 && y != -1 && x_w != -1 && y_h != -1) {
					g2d.drawImage(img, 0, 0, w, h, x, y, x_w, y_h, null);
				} else if (x_w != -1 && y_h != -1) {
					g2d.drawImage(img, 0, 0, w, h, 0, 0, x_w, y_h, null);
				} else {
					g2d.drawImage(img, 0, 0, w, h, null);
				}
				if (!ValidatorHelper.isEmpty(wimgs)) {
					for (int wi = 0; wi < wimgs.length; wi++) {
						Image wimg = wimgs[wi];
						int w1 = wimg.getWidth(null); /* 得到水图1宽 */
						int h1 = wimg.getHeight(null); /* 得到水图1高 */
						if (w1 != -1 && h1 != -1) {
							g2d.drawImage(wimg, w - w1 - 12, h - h1 - 10, w1, h1, null);
						}
					}
				}
				/*
				 * Graphics g = tag.getGraphics(); if(x!=-1 && y!=-1 && x_w!=-1
				 * && y_h!=-1){ g.drawImage(img, 0, 0, w, h, x, y, x_w, y_h,
				 * null); }else if(x_w!=-1 && y_h!=-1){ g.drawImage(img, 0, 0,
				 * w, h, 0, 0, x_w, y_h, null); }else{ g.drawImage(img, 0, 0, w,
				 * h, null); }
				 */
				gifEncoder.setDelay(delays.get(i)); // 1 frame per sec
				gifEncoder.setRepeat(0);
				gifEncoder.setQuality(0);
				gifEncoder.addFrame(tag);
				g2d.dispose();
			}
			gifEncoder.finish();
			out.close();
		} else {
			logger.error("GIF 文件错误！");
		}
	}

	@Override
	public boolean narrowOrEnlarge(String opath, String npath, int w, int h) {
		if (ValidatorHelper.isEmpty(opath) || ValidatorHelper.isEmpty(npath)) {
			return false;
		}
		GifDecoder gifDecoder = new GifDecoder();
		boolean bea = false;
		final int ow = w; // 指定的尺寸不在计算中变化
		final int oh = h; // 指定的尺寸不在计算中变化
		double wd = 0;
		double hd = 0;
		String ws = "", hs = "";
		try {
			Image img = new ImageIcon(opath).getImage();
			int width = img.getWidth(null); // 得到源图宽
			int height = img.getHeight(null); // 得到源图长
			if (width == -1 || height == -1) {
				return false;
			}
			// 同时指定宽高
			if (w > width) {
				w = width;
			}
			if (h > height) {
				h = height;
			}
			if (w > 0 && h == 0) {
				// 计算出宽度的缩放比例
				wd = ArithHelper.div(w, width, 10);
				hd = ArithHelper.mul(wd, height);
				hd = ArithHelper.round(hd, 0); // 四舍五入保留小数点0位
				hs = String.valueOf(hd).substring(0, String.valueOf(hd).indexOf("."));
				h = Integer.parseInt(hs); // 按比例缩小高度
				if (h < 1) {
					h = height;
				}
			} else if (h > 0 && h < height && w == 0) {
				hd = ArithHelper.div(h, height, 10);
				wd = ArithHelper.mul(hd, width);
				wd = ArithHelper.round(wd, 0); // 四舍五入保留小数点0位
				ws = String.valueOf(wd).substring(0, String.valueOf(wd).indexOf("."));
				w = Integer.parseInt(ws); // 按比例缩小高度
				if (w < 1) {
					w = width;
				}
			} else if (w > 0 && h > 0) {
				// 计算出宽度的缩放比例
				wd = ArithHelper.div(ow, width, 10);
				hd = ArithHelper.mul(wd, height);
				hd = ArithHelper.round(hd, 0); // 四舍五入保留小数点0位
				hs = String.valueOf(hd).substring(0, String.valueOf(hd).indexOf("."));
				h = Integer.parseInt(hs); // 按比例缩小高度
				if (h < 1) {
					h = height;
				}
				if (h < oh) {// 如果指定小图的比例不符合原图的比例
					h = oh;
					hd = ArithHelper.div(oh, height, 10);
					wd = ArithHelper.mul(hd, width);
					wd = ArithHelper.round(wd, 0); // 四舍五入保留小数点0位
					ws = String.valueOf(wd).substring(0, String.valueOf(wd).indexOf("."));
					w = Integer.parseInt(ws); // 按比例缩小高度
					if (w < 1) {
						w = width;
					}
				}
			}
			FileInputStream fis = new FileInputStream(new File(opath));
			BufferedInputStream bis = new BufferedInputStream(fis);
			gifDecoder.read(bis); // 读取GIF文件
			int n = gifDecoder.getFrameCount(); // 读取GIF帧数
			List<BufferedImage> imgList = new ArrayList<BufferedImage>();
			List<Integer> delays = new ArrayList<Integer>();
			for (int i = 0; i < n; i++) {
				BufferedImage frame = gifDecoder.getFrame(i); // frame i
				int t = gifDecoder.getDelay(i); // GIF帧数间隔时间
				imgList.add(frame);
				delays.add(t);
			}
			try {
				this.gif(imgList, delays, null, npath, w, h, -1, -1, -1, -1);
				bea = true;
				fis.close();
				bis.close();
			} catch (Exception e) {
				logger.error(e.toString());
			}
		} catch (IOException e) {
			logger.debug(e.toString());
		}
		return bea;
	}

	@Override
	public boolean watermark(String opath, String npath, String wpath) {
		Image image = new ImageIcon(opath).getImage();
		return this.watermark(image, opath, npath, wpath);
	}

	@Override
	public boolean watermark(String opath, String npath, String wpath, int minwidth, int minheight) {
		Image image = new ImageIcon(opath).getImage();
		if (image.getWidth(null) < minwidth || image.getHeight(null) < minheight) {
			return false;
		} else {
			return this.watermark(image, opath, npath, wpath);
		}
	}

	private boolean watermark(Image image, String opath, String npath, String wpath) {
		boolean bea = false;
		try {
			// Image src = new ImageIcon(opath).getImage();
			int w = image.getWidth(null); /* 得到源图宽 */
			int h = image.getHeight(null); /* 得到源图高 */
			if (w == -1 || h == -1) {
				return false;
			}
			BufferedImage tag = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
			tag.getGraphics().drawImage(image, 0, 0, w, h, null);
			GifDecoder gifDecoder = new GifDecoder();
			FileInputStream fis = new FileInputStream(new File(opath));
			BufferedInputStream bis = new BufferedInputStream(fis);
			gifDecoder.read(bis); // 读取GIF文件
			int n = gifDecoder.getFrameCount(); // 读取GIF帧数
			List<BufferedImage> imgList = new ArrayList<BufferedImage>();
			List<Integer> delays = new ArrayList<Integer>();
			for (int i = 0; i < n; i++) {
				BufferedImage frame = gifDecoder.getFrame(i); // frame i
				int t = gifDecoder.getDelay(i); // GIF帧数间隔时间
				imgList.add(frame);
				delays.add(t);
			}
			try {
				Image[] wimgs = new Image[1];
				wimgs[0] = new ImageIcon(wpath).getImage();// 构造Image对象
				this.gif(imgList, delays, wimgs, npath, w, h, -1, -1, -1, -1);
				bea = true;
			} catch (Exception e) {
				logger.error(e.toString());
			}
			bis.close();
			fis.close();
		} catch (IOException e) {
			logger.error(e.toString());
		}
		return bea;
	}

	@Override
	public boolean resize(String opath, String npath, int w, int h) {
		return this.clip(opath, npath, w, h, 0, 0, w, h);
	}

	@Override
	public boolean scaled(String opath, String npath, int width, int height) {
		return this.narrowOrEnlarge(opath, npath, width, height);
	}

	public boolean zoomIn(String opath, String npath, int w, int h) {
		return false;
	}
	
	public boolean zoomOut(String opath, String npath, int w, int h) {
		Image img = new ImageIcon(opath).getImage();
		int width = img.getWidth(null); // 得到源图宽
		int height = img.getHeight(null); // 得到源图长
		if (w == 0 && h < height) {
			return this.narrowOrEnlarge(opath, npath, w, h);
		} 
		else if (h == 0 && w < width) {
			return this.narrowOrEnlarge(opath, npath, w, h);
		} 
		else if(w > 0 && h > 0 && w <= width && h <= height){
			return this.narrowOrEnlarge(opath, npath, w, h);
		}
		else {
			try {
				return com.yeqiangwei.commons.io.FileHelper.copyFile(opath, npath);
			} catch (IOException e) {
				logger.error(e.toString());
			}
		}
		return false;
	}

	@Override
	public boolean setSquare(String opath, String npath) {
		Image image = new ImageIcon(opath).getImage();
		double w = image.getWidth(null);
		double h = image.getHeight(null);
		int width = 0;
		int height = 0;
		if (w != h) {
			if (w > h) {
				width = height = TypeChange.doubleToInt(h);
			} else if (w < h) {
				width = height = TypeChange.doubleToInt(w);
			}
			this.inciseTopAndCenter(opath, npath, width, height);
		} else {
			try {
				com.yeqiangwei.commons.io.FileHelper.copyFile(opath, npath);
			} catch (IOException e) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 靠顶部且横向居中部分图片
	 */
	@Override
	public boolean inciseTopAndCenter(String opath, String npath, int w, int h) {
		Image image = new ImageIcon(opath).getImage();
		int ow = image.getWidth(null);
		int y = 0;
		int x = (ow - w) / 2;
		if (x < 0) {
			x = 0;
		}
		return super.clip(opath, npath, w, h, x, y, w + x, h + y);
	}

	@Override
	public boolean clip(BufferedInputStream bis, String filePathAndName, int w, int h, int x, int y, int x_w, int y_h) {
		boolean bea = false;
		GifDecoder gifDecoder = new GifDecoder();
		try {
			gifDecoder.read(bis); // 读取GIF文件
			int n = gifDecoder.getFrameCount(); // 读取GIF帧数
			List<BufferedImage> imgList = new ArrayList<BufferedImage>();
			List<Integer> delays = new ArrayList<Integer>();
			for (int i = 0; i < n; i++) {
				BufferedImage frame = gifDecoder.getFrame(i); // frame i
				int t = gifDecoder.getDelay(i); // GIF帧数间隔时间
				imgList.add(frame);
				delays.add(t);
			}
			try {
				this.gif(imgList, delays, null, filePathAndName, w, h, x, y, x_w, y_h);
				bea = true;
			} catch (Exception e) {
				logger.error(e.toString());
			}
			bis.close();
		} catch (IOException e) {
			logger.error(e.toString());
		}
		return bea;
	}
}
